/*
   DOES NOT USE THE BUILT-IN DETECTION FUNCTIONALITY!!!
   
alert tcp $EXTERNAL_NET any -> $HOME_NET 42 (msg:"EXPLOIT WINS replication request memory corruption attempt"; flow:to_server,established; content:"|00 00 00 03 00 00 00 02|"; offset:12; depth:8; metadata:policy balanced-ips drop, policy security-ips drop, service netbios-ns; reference:cve,2009-1923; reference:url,technet.microsoft.com/en-us/security/bulletin/MS09-039; classtype:attempted-admin; sid:15848; rev:1;)
*/
/*
 * Use at your own risk.
 *
 * Copyright (C) 2005-2008 Sourcefire, Inc.
 * 
 * This file is autogenerated via rules2c, by Brian Caswell <bmc@sourcefire.com>
 */


#include "sf_snort_plugin_api.h"
#include "sf_snort_packet.h"

#include "so-util.h"

//#define DEBUG 1
#ifdef DEBUG
#define DEBUG_WRAP(code) code
#else
#define DEBUG_WRAP(code)
#endif

/* declare detection functions */
int rule15848eval(void *p);

/* declare rule data structures */
/* precompile the stuff that needs pre-compiled */
/* flow:established, to_server; */
static FlowFlags rule15848flow0 = 
{
    FLOW_ESTABLISHED|FLOW_TO_SERVER
};

static RuleOption rule15848option0 =
{
    OPTION_TYPE_FLOWFLAGS,
    {
        &rule15848flow0
    }
};
#ifndef CONTENT_FAST_PATTERN
#define CONTENT_FAST_PATTERN 0
#endif
// content:"|00 00 00 03 00 00 00 02|", offset 12, depth 8, fast_pattern; 
static ContentInfo rule15848content1 = 
{
    (uint8_t *) "|00 00 00 03 00 00 00 02|", /* pattern (now in snort content format) */
    8, /* depth */
    12, /* offset */
    CONTENT_FAST_PATTERN|CONTENT_BUF_NORMALIZED, /* flags */
    NULL, /* holder for boyer/moore PTR */
    NULL, /* more holder info - byteform */
    0, /* byteform length */
    0 /* increment length*/
};

static RuleOption rule15848option1 = 
{
    OPTION_TYPE_CONTENT,
    {
        &rule15848content1
    }
};

/* references for sid 15848 */
/* reference: cve "2009-1923"; */
static RuleReference rule15848ref1 = 
{
    "cve", /* type */
    "2009-1923" /* value */
};

/* reference: url "technet.microsoft.com/en-us/security/bulletin/MS09-039"; */
static RuleReference rule15848ref2 = 
{
    "url", /* type */
    "technet.microsoft.com/en-us/security/bulletin/MS09-039" /* value */
};

static RuleReference *rule15848refs[] =
{
    &rule15848ref1,
    &rule15848ref2,
    NULL
};

/* metadata for sid 15848 */
/* metadata:service netbios-ns, policy balanced-ips drop, policy security-ips drop; */
static RuleMetaData rule15848service1 = 
{
    "service netbios-ns"
};


//static RuleMetaData rule15848policy1 = 
//{
//    "policy balanced-ips drop"
//};
//
//static RuleMetaData rule15848policy2 = 
//{
//    "policy security-ips drop"
//};


static RuleMetaData *rule15848metadata[] =
{
    &rule15848service1,
//    &rule15848policy1,
//    &rule15848policy2,
    NULL
};

RuleOption *rule15848options[] =
{
    &rule15848option0,
    &rule15848option1,
    NULL
};

Rule rule15848 = {
   
   /* rule header, akin to => tcp any any -> any any               */{
       IPPROTO_TCP, /* proto */
       "$EXTERNAL_NET", /* SRCIP     */
       "any", /* SRCPORT   */
   
       0, /* DIRECTION */
       "$HOME_NET", /* DSTIP     */
   
       "42", /* DSTPORT   */
   },
   /* metadata */
   { 
       3,  /* genid */
       15848, /* sigid */
       7, /* revision */
   
       "attempted-admin", /* classification */
       0,  /* hardcoded priority XXX NOT PROVIDED BY GRAMMAR YET! */
       "OS-WINDOWS WINS replication request memory corruption attempt",     /* message */
       rule15848refs /* ptr to references */
       ,rule15848metadata
   },
   rule15848options, /* ptr to rule options */
   &rule15848eval, /* DO NOT use the built in detection function */
   0 /* am I initialized yet? */
};


/* detection functions */
int rule15848eval(void *p) {
    const uint8_t *cursor_normal = 0;
    SFSnortPacket *sp = (SFSnortPacket *) p;

    const uint8_t *beg_of_payload, *end_of_payload;

    // The version fields are read as signed values
    // Provided PoC has 0x80000000fffffffe - 0x0000000000000000
    // resulting in a negative value.
    uint32_t max_version_low;
    uint32_t min_version_low;     
    uint32_t check;

    DEBUG_WRAP(const char *name="rule15848eval";)
    DEBUG_WRAP(printf("%s: enter\n", name);)

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_server;
    if (checkFlow(p, rule15848options[0]->option_u.flowFlags) > 0 ) {
        // content:"|00 00 00 03 00 00 00 02|", offset 12, depth 8, fast_pattern;
        if (contentMatch(p, rule15848options[1]->option_u.content, &cursor_normal) > 0) {

            DEBUG_WRAP(printf("%s : |00 00 00 03 00 00 00 02| found\n", name);)
                
            if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
               return RULE_NOMATCH;

            cursor_normal += 8; // skip owner ipv4 address field and max_ver high 32 bits
            
            if (cursor_normal + 12 > end_of_payload)
                return RULE_NOMATCH;

            max_version_low = read_big_32(cursor_normal);
            DEBUG_WRAP(printf("%s : %x\n", name, max_version_low);)

            cursor_normal += 8;
            min_version_low = read_big_32(cursor_normal);
            DEBUG_WRAP(printf("%s : %x\n", name, min_version_low);)

            // This equation isn't minimized to min_version_low - max_version_low == 2 to
            // preserve the possibility that integer overflow triggers the vuln
            check = (max_version_low - min_version_low + 2) * 72;

            if (check == 0)
                return RULE_MATCH;
        }
    }
    return RULE_NOMATCH;
}

/*
Rule *rules[] = {
    &rule15848,
    NULL
};
*/
